
/**
两种用例 两种写法
 */
class Scheduler {
  constructor(limit) {
    this.limit = limit;
    this.queue = [];
    this.count = 0;
  }
  run(fn, ...args) {
    return new Promise((resolve, reject) => {
      this.queue.push({fn, args, resolve, reject});
      const next = () => {
        if(this.count < this.limit && this.queue.length > 0) {
          this.count++;
          const {fn, args, resolve, reject} = this.queue.shift();
          fn(...args).then(resolve, reject).finally(() => {
            this.count--;
            next();
          });
        }
      }
      next();
    })
  }
}
// 性能较差
// class Scheduel {
//   constructor() {
//     this.queue = new Set();
//   }
//   add(promiseCreator) {
//     if(this.queue.size >= 2) {
//       return Promise.race(Array.from(this.queue)).finally(() => this.add(promiseCreator))
//     }else {
//       const promiseInstance = promiseCreator();
//       this.queue.add(promiseInstance);
//       return promiseInstance.finally(() => this.queue.delete(promiseInstance))
//     }
//   }
// }

const _scheduel = new Scheduler(2);
const timer = (time) => new Promise(resolve => {
  setTimeout(resolve,time);
})
const addTask = (time, order) => {
  _scheduel.run(() => timer(time).then(() => console.log(order)), order)
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
//2 3 1 4


// 方法3
class Scheduel {
  constructor(limit) {
    this.limit = limit; // 并发限制数量
    this.queue = []; // 任务队列
    this.running = 0; // 当前正在运行的任务数
  }
  add(task) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject });
      this.run();
    });
  }
  run() {
    if(this.running < this.limit && this.queue.length > 0) {
      const { task, resolve, reject } = this.queue.shift();
      this.running++;
      task().then(resolve, reject).finally(() => {
        this.running--;
        this.run();
      });
    }
  }
}

const scheduel = new Scheduel(2);
// 开始执行输出 i start 结束执行输出 i finish
const asyncTask = (i) => {
  return new Promise((resolve, reject) => {
    console.log(`${i} start`)
    setTimeout(() => {
      console.log(`${i} finish`)
      resolve()
    }, i*1000)
  })
}
// for(let i=1;i<=5;i++) {
//   scheduel.add(()=>asyncTask(i))
// }
